﻿using System;
using System.Collections.Generic;
using AvantGameMachine.Graphics;
using AvantGameMachine.States;
using AvantGameMachine.DataManagement;
using AvantGameMachine.Clients;
using AvantGameMachine.Events;
using AvantGameMachine.Input.Keyboard;
using AvantGameMachine.Graphics.Animators;

namespace AvantGameMachine.Menu
{
    class MenuStatesProvider : StatesProvider, ILocalEventReceiver
    {
        private MenuLoader ml;
        private RenderObject[] menuObjects;
        private RenderObject menuMain;
        private Font fText;
        private List<MenuClientData> clientData = new List<MenuClientData>();
        private int selected = 0;
        private float step;
        float circleRad = 4.0f;

        public override void EnterState(string _newState)
        {
            base.EnterState(_newState);
            switch (_newState)
            {
                case "LoadMenu":
                    ml = AGMPlatform.SystemCamera.CreateNew2DObject<MenuLoader>("MenuLoader");
                    ml.LoadBasic();
                    ml.Start();
                    break;
                case "PreLoadGames":
                    AGMPlatform.log.Debug("Preloading modules...");
                    break;
                case "ShowMenu":
                    CreateMenu();
                    AGMPlatform.EManager.RegisterLocalReceiver(this, EventTypes.EVENT_TYPE_KEY);
                    break;
            }
        }

        public override void Update(string _currentState)
        {
            base.Update(_currentState);
            switch (_currentState)
            {
                case "LoadMenu":
                    if (ml.IsLoadingFinish)
                    {
                        ml.Dispose();
                        this.ChangeState("PreLoadGames");
                    }
                    break;
                case "PreLoadGames":
                    foreach (PreloadedClient prc in AGMPlatform.ClManager.ClientsList)
                    {
                        clientData.Add(new MenuClientData(prc));
                    }

                    ChangeState("ShowMenu");
                    break;
                case "ShowMenu":
                    break;
            }
        }

        internal void CreateMenu()
        {
            fText = AGMPlatform.TRManager.GetNewFont(new Address("Menu/309.ttf"), 72);
            // Get the number of preloader games.
            int npg = clientData.Count;
            menuMain = AGMPlatform.SystemCamera.CreateNew3DObject<RenderObject>("MenuMain");
            menuObjects = new RenderObject[npg];
            float startAngle = 0.0f;
            float currentAngle = startAngle;
            float endAngle = (float)(2.0 * Math.PI);
            step = (float)((endAngle - startAngle) / (double)npg);

            for (int i = 0; i < npg; i++)
            {
                menuObjects[i] = menuMain.CreateNew<RenderObject>("Menu" + npg);
                menuObjects[i].PlaneBox(4.0f, 2.0f, 0.0f);
                menuObjects[i].GetFace(0).FaceMaterial.SetColor(0, Color.Red());
                menuObjects[i].GetFace(0).FaceMaterial.SetColor(3, Color.Red());

                menuObjects[i].GetFace(0).FaceMaterial.SetColor(1, Color.Black());
                menuObjects[i].GetFace(0).FaceMaterial.SetColor(2, Color.Black());
                menuObjects[i].Position = new PosVector(0.0f, (float)Math.Sin(currentAngle) * circleRad, (float)Math.Cos(currentAngle) * circleRad);

                float ytext = 0.0f;

                for (int j = 0; j < clientData[i].GetNumLines(); j++)
                {
                    TextRenderObject obj = menuObjects[i].CreateNew<TextRenderObject>("t"+j);
                    obj.TextFont = fText;
                    obj.Text = clientData[i].GetLine(j);
                    obj.ScaleX = 0.0019f;
                    obj.ScaleY = 0.0019f;
                    obj.Alignement = TextAlignement.AlignementLeft;
                    obj.AlignedPosX = -0.8f;
                    obj.PositionY = ytext;
                    obj.PositionY += obj.Parent.BoundCube.Max.Y;
                    ytext -= obj.TextFont.FontSize.Heightf * obj.ScaleY;
                    obj.View = TextView.ViewTop;
                }
                
                Face iconFace = menuObjects[i].CreateNew<Face>("icon");
                iconFace.CreateBox(1.0f, 1.0f, 0.0f);
                iconFace.PositionX = iconFace.Parent.BoundCube.Min.X+0.6f;
                iconFace.FaceMaterial = new Material(clientData[i].Icon);

                currentAngle += step;
            }
        }

        public void ReceiveLocalEvent(Event _event)
        {
            switch (_event.Type)
            {
                case EventTypes.EVENT_TYPE_KEY:
                    switch (((KeyboardEventData)_event.Data).Key)
                    {
                        case Keys.KEY_DOWN:
                            for (int i = 0; i < 1; i++)
                            {
                                ChangePosVectorAnimator rAnim = new ChangePosVectorAnimator();
								rAnim.StartValue = menuObjects[i].Position;
								rAnim.EndValue = menuObjects[(i+i)>=menuObjects.Length?0:i+i].Position;
                                rAnim.Duration = 2000;
                                rAnim.UserAnim += this.MoveMenuObject;
                                menuObjects[i].AddAndStartAnimator(rAnim);
                            }
                            break;
                    }
                    break;
            }
        }

        private bool MoveMenuObject(RangeTimeAnimator _anim)
        {
            float angle = _anim.Delta * step;
            _anim.AnimObject.Position = new PosVector(0.0f, (float)Math.Sin(angle) * circleRad, (float)Math.Cos(angle) * circleRad);

            return true;
        }
    }
}
